package com.cgy.utils.netx.ssh.client;

import org.apache.commons.lang3.StringUtils;
import org.apache.sshd.client.channel.ClientChannel;
import org.apache.sshd.client.session.ClientSession;

import com.cgy.utils.netx.client.INetworkClientLibrary;
import com.cgy.utils.netx.config.ClientConfig;
import com.google.common.base.Preconditions;

import java.io.InputStream;

/**
 * @author CHTK
 */
public class SshClient implements INetworkClientLibrary<ClientChannel> {

    private org.apache.sshd.client.SshClient sshClient;

    private String username;
    private String password;
    private String host;
    private int port;
    private int connectionTimeoutMs;
    private ClientSession session;
    private ClientChannel channel;

    @Override
    public INetworkClientLibrary<ClientChannel> initial(ClientConfig clientConfig, Object...extConfig) {
        Preconditions.checkArgument(null != clientConfig);
        Preconditions.checkArgument(clientConfig.getPort() > 0);
        Preconditions.checkArgument(StringUtils.isNotBlank(clientConfig.getUsername()));
        Preconditions.checkArgument(StringUtils.isNotBlank(clientConfig.getPassword()));
        Preconditions.checkArgument(StringUtils.isNotBlank(clientConfig.getIp()));

        this.username = clientConfig.getUsername();
        this.host = clientConfig.getIp();
        this.port = clientConfig.getPort();
        this.password = clientConfig.getPassword();
        this.connectionTimeoutMs = clientConfig.getConnectionTimeoutMs();

        sshClient = org.apache.sshd.client.SshClient.setUpDefaultClient();
        return this;
    }

    @Override
    public INetworkClientLibrary initial(InputStream inputStream) {
        return this;
    }

    @Override
    public INetworkClientLibrary<ClientChannel> connect() throws Exception {
        sshClient.start();

        this.session = sshClient.connect(username, host, port).getSession();
        session.addPasswordIdentity(password);
        session.auth().verify(connectionTimeoutMs <= 0 ? 10000 : connectionTimeoutMs);

        this.channel = session.createChannel(ClientChannel.CHANNEL_SHELL);
       /* channel.setIn(new NoCloseInputStream(System.in));
        channel.setOut(new NoCloseOutputStream(System.out));
        channel.setErr(new NoCloseOutputStream(System.err));
        channel.open();
        channel.waitFor(Arrays.asList(ClientChannelEvent.CLOSED), 0);*/
        return this;
    }

    @Override
    public void release() throws Exception {
        session.close();
        sshClient.stop();
    }

    @Override
    public ClientChannel getClient() throws Exception {
        return channel;
    }
}
